package com.ps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import com.ps.constant.MessageConstant;
import com.ps.constant.StatusConstant;
import com.ps.dto.SetmealDTO;
import com.ps.dto.SetmealPageQueryDTO;
import com.ps.entity.Category;
import com.ps.entity.Medicine;
import com.ps.entity.Setmeal;
import com.ps.entity.SetmealMedicine;
import com.ps.exception.DeletionNotAllowedException;
import com.ps.exception.SetmealEnableFailedException;
import com.ps.mapper.MedicineMapper;
import com.ps.mapper.SetmealMapper;
import com.ps.mapper.SetmealMedicineMapper;
import com.ps.result.PageResult;
import com.ps.service.CategoryService;
import com.ps.service.MedicineService;
import com.ps.service.SetmealMedicineService;
import com.ps.service.SetmealService;
import com.ps.vo.MedicineItemVO;
import com.ps.vo.SetmealVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SetmealServiceImpl extends  ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
    private final SetmealMapper setmealMapper;
    private final SetmealMedicineMapper setmealMedicineMapper;
    private final SetmealMedicineService setmealMedicineService;
    private final MedicineMapper medicineMapper;
    private final MedicineService medicineService;
    @Transactional
    public void saveWithMedicine(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        //向药品组合表插入数据
        save(setmeal);
        //获取生成的药品组合id
        Long setmealId = setmeal.getId();
        List<SetmealMedicine> setmealMedicinees = setmealDTO.getSetmealMedicinees();
        setmealMedicinees.forEach(setmealMedicine -> {
            setmealMedicine.setSetmealId(setmealId);
        });
        //保存药品组合和药品的关联关系
        setmealMedicineService.saveBatch(setmealMedicinees);
    }

    public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {
        int pageNum = setmealPageQueryDTO.getPage();
        int pageSize = setmealPageQueryDTO.getPageSize();

        PageHelper.startPage(pageNum, pageSize);
        Page<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Transactional
    public void deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            Setmeal setmeal = setmealMapper.selectById(id);
            if(StatusConstant.ENABLE == setmeal.getStatus()){
                //起售中的药品组合不能删除
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        });
        ids.forEach(setmealId -> {
            //删除药品组合表中的数据
            removeById(setmealId);
            //删除药品组合药品关系表中的数据
            setmealMedicineMapper
                    .delete(new QueryWrapper<SetmealMedicine>()
                            .eq("setmeal_id",setmealId));
        });
    }

    public SetmealVO getByIdWithMedicine(Long id) {
        Setmeal setmeal = setmealMapper.selectById(id);
        List<SetmealMedicine> setmealMedicinees =setmealMedicineService.lambdaQuery()
                .eq(SetmealMedicine::getSetmealId, id)
                .list();
        SetmealVO setmealVO = new SetmealVO();
        BeanUtils.copyProperties(setmeal, setmealVO);
        setmealVO.setSetmealMedicinees(setmealMedicinees);
        return setmealVO;
    }
    @Transactional
    public void update(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        //1、修改药品组合表，执行update
        lambdaUpdate()
                .eq(Setmeal::getId, setmeal.getId())
                .update(setmeal);
        //药品组合id
        Long setmealId = setmealDTO.getId();
        //2、删除药品组合和药品的关联关系，操作setmeal_medicine表，执行delete
        setmealMedicineMapper.delete(new QueryWrapper<SetmealMedicine>()
                .eq("setmeal_id",setmealId));;
        List<SetmealMedicine> setmealMedicinees = setmealDTO.getSetmealMedicinees();
        setmealMedicinees.forEach(setmealMedicine -> {
            setmealMedicine.setSetmealId(setmealId);
        });
        //3、重新插入药品组合和药品的关联关系，操作setmeal_medicine表，执行insert
        setmealMedicineService.saveBatch(setmealMedicinees);
    }
    public void startOrStop(Integer status, Long id) {
        //起售药品组合时，判断药品组合内是否有停售药品，有停售药品提示"药品组合内包含未启售药品，无法启售"
        if(status == StatusConstant.ENABLE){
            //select a.* from medicine a left join setmeal_medicine b on a.id = b.medicine_id where b.setmeal_id = ?
            List<Medicine> medicineList = medicineMapper.getBySetmealId(id);
            if(medicineList != null && !medicineList.isEmpty()){
                medicineList.forEach(medicine -> {
                    if(StatusConstant.DISABLE .equals(medicine.getStatus())){
                        throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
                    }
                });
            }
        }
        Setmeal setmeal = Setmeal.builder()
                .id(id)
                .status(status)
                .build();
        lambdaUpdate().eq(Setmeal::getId, setmeal.getId())
                .set(Setmeal::getStatus, setmeal.getStatus())
                .update();
    }
    public List<Setmeal> list(Setmeal setmeal) {
        List<Setmeal> list =lambdaQuery()
                .like(Setmeal::getName,  setmeal.getName())
                .eq(Setmeal::getCategoryId, setmeal.getCategoryId())
                .eq(Setmeal::getStatus, setmeal.getStatus())
                .list();
        return list;
    }

    public List<MedicineItemVO> getMedicineItemById(Long id) {
        return setmealMapper.getMedicineItemBySetmealId(id);
    }
}
